package com.common.supply.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.common.supply.Utils.DateUtils;
import com.common.supply.Utils.Func;
import com.common.supply.common.RspEnmu;
import com.common.supply.config.exception.BusinessException;
import com.common.supply.domain.OkRequest;
import com.common.supply.domain.entity.extdata.ExtReqLog;
import com.common.supply.service.IExtReqLogService;
import com.common.supply.service.IExternalApiService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.net.SocketTimeoutException;
import java.util.Iterator;

/**
 * @author cyh
 * @date 2022/5/9 11:58 上午
 */
@Slf4j
@Service
public class ExternalApiServiceImpl implements IExternalApiService {


    @Autowired
    private IExtReqLogService extReqLogService;

    @Resource
    private OkHttpClient okHttpClient;


    @Override
    public JSONObject crsRequest(OkRequest okRequest) {

        ExtReqLog extReqLog = new ExtReqLog();
        extReqLog.setApiName(okRequest.getApiName());
        extReqLog.setReqUrl(okRequest.getUrl());
        extReqLog.setReqParam(okRequest.getParams().toString());
        extReqLog.setReqTime(DateUtils.dateTimeNow());
        extReqLog.setUserId(okRequest.getUserId());

        String apiResult = "";
        try {
            //http请求
            Response response = okHttpCrsRequest(okRequest);
            log.info("调用接口返回：{}", response.toString());
            extReqLog.setRetCode(response.code() + "");
            extReqLog.setRetMsg(response.message());

            apiResult = response.body().string();
            extReqLog.setRspResult(apiResult);

            if (404 == response.code()) {
                extReqLog.setCallStatus("0");
                return JSONObject.parseObject(apiResult);
            }

            if (200 != response.code()) {
                extReqLog.setCallStatus("0");
                throw new BusinessException(response.message(), RspEnmu.NETWORK_EXCEPTION.getRetCode());
            }
            extReqLog.setCallStatus("1");

        } catch (Exception e) {
            log.error("调用接口异常", e);
            extReqLog.setCallStatus("2");
            throw new BusinessException(e.getMessage(), RspEnmu.NETWORK_EXCEPTION);
        } finally {
            extReqLog.setResTime(DateUtils.dateTimeNow());
            extReqLogService.save(extReqLog);
        }
        return JSONObject.parseObject(apiResult);
    }

    private Response okHttpCrsRequest(OkRequest okRequest) {

        RequestBody body = null;
        if (Func.isNotEmpty(okRequest.getReqEnum())) {
            MediaType mediaType = MediaType.parse(okRequest.getReqEnum().getType());
            body = RequestBody.create(mediaType, okRequest.getParams().toString());
        }

        Request request = new Request.Builder()
                .url(okRequest.getUrl())
                .method(okRequest.getReqMethod(), "GET".equalsIgnoreCase(okRequest.getReqMethod()) ? null : body)
                .headers(okRequest.getHeaders())
                .build();
        // 链接池使用
//        OkHttpClient client = new OkHttpClient().newBuilder()
//                //设置连接超时时间
//                .connectTimeout(160, TimeUnit.SECONDS)
//                //设置读取超时时间
//                .readTimeout(160, TimeUnit.SECONDS)
//                .build();

        int reentryNum = 3;
        Response execute = null;
        while (reentryNum > 0) {
            try {
                execute = okHttpClient.newCall(request).execute();
                reentryNum = 0;
            } catch (SocketTimeoutException e) {
                reentryNum--;
                log.error("{}请求超时，还剩{}次", okRequest.getApiName(), reentryNum);
            } catch (Exception e) {
                reentryNum--;
                log.error("{}请求超时，还剩{}次", okRequest.getApiName(), reentryNum);
            }
        }

        if (execute == null) {
            throw new BusinessException(RspEnmu.NETWORK_EXCEPTION);
        }
        return execute;
    }


}
